package cn.com.yang.server.jetty;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.management.ManagementFactory;

import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.deploy.PropertiesConfigurationManager;
import org.eclipse.jetty.deploy.bindings.DebugListenerBinding;
import org.eclipse.jetty.deploy.providers.WebAppProvider;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.rewrite.handler.RewriteHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.CustomRequestLog;
import org.eclipse.jetty.server.DebugListener;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.LowResourceMonitor;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnectionStatistics;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.webapp.Configuration;

/**
 * https://www.lmlphp.com/user/58291/article/item/622776/
 * 配置jetty服务器实例的典型方法是通过jetty.xml和相关配置文件。
 * 但是，Jetty XML配置格式只是对代码中可以执行的操作的简单实现；编写完全符合jetty.xml配置功能的嵌入式代码非常简单，
 * 以下LikeJettyXml示例在代码中呈现从配置文件中获取的行为：
 * jetty.xml
 * jetty-jmx.xml
 * jetty-http.xml
 * jetty-https.xml
 * jetty-deploy.xml
 * jetty-stats.xml
 * jetty-requestlog.xml
 * jetty-lowresources.xml
 * test-realm.xml
 * 
 * TODO
 * @author yangyijin
 * @since 2023年5月19日-上午10:43:19
 */
public class LikeJettyXML {
	
	public static void main(String[] args) throws Exception {
		//Path to as-built jetty-distribution directory
		String jettyHomeBuild = "../../jetty-ditribution/ditribution";
		//Find jetty home and base directories
		String homePath =System.getProperty("jetty.home",jettyHomeBuild);
		File start_jar = new File(homePath,"start.jar");
		if(!start_jar.exists()) {
			homePath = jettyHomeBuild = "jetty-ditribution/target/ditribution";
			start_jar = new File(homePath,"start.jar");
			if (!start_jar.exists()) {
				throw new FileNotFoundException(start_jar.toString());
			}
		}
		File homeDir = new File(homePath);
		String basePath = System.getProperty("jetty.base",homeDir +"/demo-base");
		File baseDir = new File(basePath);
		if (!baseDir.exists()) {
			throw new FileNotFoundException(baseDir.getAbsolutePath());
		}
		// Configure jetty.home and jetty.base system properties
		String jetty_home = homeDir.getAbsolutePath();
		String jetty_base = baseDir.getAbsolutePath();
		System.setProperty("jetty.home",jetty_home);
		System.setProperty("jetty.base",jetty_base);
		// ==jetty.xml==
		// Setup ThreadPool
		QueuedThreadPool threadPool = new QueuedThreadPool();
		threadPool.setMaxThreads(500);
		// Server
		Server server = new Server(threadPool);
		// Scheduler,添加到server
		server.addBean(new ScheduledExecutorScheduler());
		// HTTP Configuration
		HttpConfiguration http_config = new HttpConfiguration();
		http_config.setSecureScheme("https");
		http_config.setSecurePort(8443);
		http_config.setOutputBufferSize(32768);// 32768 / 1024
		http_config.setRequestHeaderSize(8192);// 8192 /1024 =8M
		http_config.setResponseHeaderSize(8192);
		http_config.setSendServerVersion(true);
		http_config.setSendDateHeader(false);
//		http_config.addCustomizer(new ForwardedRequestCustomizer());
		// handler Structure
		HandlerCollection handlers = new HandlerCollection();
		ContextHandlerCollection contexts = new ContextHandlerCollection();
		handlers.setHandlers(new Handler[] {contexts,new DefaultHandler()});
		server.setHandler(handlers);
		// Extra options
		server.setDumpAfterStart(false);
		server.setDumpBeforeStop(false);
		server.setStopAtShutdown(true);
		// ===jetty-jmx.xml===
		MBeanContainer mbContainer = 
				new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
		server.addBean(mbContainer);
		// ===jetty-http.xml===
		ServerConnector http  = new ServerConnector(server,new HttpConnectionFactory(http_config));
		http.setPort(8080);
		http.setIdleTimeout(30000);
		// 添加到server
		server.addConnector(http);
		// ===jetty-https.xml===
		// SSL Context Factory
		SslContextFactory sslContextFactory = new SslContextFactory();
		sslContextFactory.setKeyStorePath(jetty_home+"/../../../jetty-server/src/test/config/etc/keystore");
		sslContextFactory.setKeyStorePassword("OBF:1231uidsadfgqary231");//自己定义
		sslContextFactory.setKeyManagerPassword("OBF:sdadw1312csdvasdf234");
		sslContextFactory.setTrustStorePath(jetty_home+"/../../../jetty-server/src/test/config/etc/keystore");
		sslContextFactory.setTrustStorePassword("OBF:1231uidsadfgqary231");
		sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA",
				"SSL_DHE_RSA_WITH_DES_CBC_SHA","SSL_DHE_DSS_WITH_DES_CBC_SHA",
				"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
				"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
				"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
				"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
		// SSL HTTP Configuration
		HttpConfiguration httpsConfig = new HttpConfiguration(http_config);
		httpsConfig.addCustomizer(new SecureRequestCustomizer());
		// SSL Connector
		ServerConnector ssConnector = new ServerConnector(server,
				new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
				new HttpConnectionFactory(httpsConfig));
		ssConnector.setPort(8443);
		//添加到server
		server.addConnector(ssConnector);
		// === jetty-deploy.xml===
		DeploymentManager deployer = new DeploymentManager();
		DebugListener debug = new DebugListener(System.err,true,true,true);
		// 添加到server
		server.addBean(debug);
		deployer.addLifeCycleBinding(new DebugListenerBinding(debug));
		deployer.setContexts(contexts);
		deployer.setContextAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPartern",
				".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");
		WebAppProvider weProvider = new WebAppProvider();
		weProvider.setMonitoredDirName(jetty_base+"/webapps");
		weProvider.setDefaultsDescriptor(jetty_home+"/etc/webdefault.xml");
		weProvider.setScanInterval(1);
		weProvider.setExtractWars(true);
		weProvider.setConfigurationManager(new PropertiesConfigurationManager());
		deployer.addAppProvider(weProvider);
		//添加到server
		server.addBean(deployer);
		// ==setup jetty plus==
		Configuration.ClassList classList = Configuration.ClassList.setServerDefault(server);
		classList.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
				"org.eclipse.jetty.plus.webapp.EnvConfiguration",
				"org.eclipse.jetty.plus.webapp.PlusConfiguration");
		classList.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
				"org.eclipse.jetty.annotations.AnnotationConfiguration");
		// ===jetty-stats.xml ===
		StatisticsHandler statics = new StatisticsHandler();
		statics.setHandler(server.getHandler());
		server.setHandler(statics);
		// 添加到server
		ServerConnectionStatistics.addToAllConnectors(server);
		// ===Rewrite Handler
		RewriteHandler rwWrite = new RewriteHandler();
		rwWrite.setHandler(server.getHandler());
		server.setHandler(rwWrite);
		// ===jetty-requestlog.xml ===
		
//		CustomRequestLog requestLog = new CustomRequestLog(jetty_home+"/logs/yyyy_mm_dd.request.log");
		NCSARequestLog requestLog = new NCSARequestLog();
		requestLog.setFilename(jetty_home+"/logs/yyyy_mm_dd.request.log");
		requestLog.setFilenameDateFormat("yyyy_MM_dd");
		requestLog.setRetainDays(90);
		requestLog.setAppend(true);
		requestLog.setExtended(true);
		requestLog.setLogCookies(false);
		requestLog.setLogTimeZone("GMT");
		RequestLogHandler requestLogHandler =new RequestLogHandler();
		requestLogHandler.setRequestLog(requestLog);
		handlers.addHandler(requestLogHandler);
		// ==jetty-lowresources.xml ===
		LowResourceMonitor lowResourceMonitor  = new LowResourceMonitor(server);
		lowResourceMonitor.setPeriod(1000);
		lowResourceMonitor.setLowResourcesIdleTimeout(200);
		lowResourceMonitor.setMonitorThreads(true);
		lowResourceMonitor.setMaxConnections(0);
		lowResourceMonitor.setMaxMemory(0);
		lowResourceMonitor.setMaxLowResourcesTime(500);
		server.addBean(lowResourceMonitor);
		// ===test-realm.xml ===
		HashLoginService login = new HashLoginService();
		login.setName("Test Realm");
		login.setConfig(jetty_base+"/etc/realm.properties");
		login.setHotReload(false);
		server.addBean(login);
		// Start the server
		server.start();
		server.join();
	}
}
